package com.ssm.security;

import com.ssm.entity.*;
import com.ssm.mapper.AppUserMapper;
import com.ssm.mapper.SysRoleMapper;
import com.ssm.mapper.SysUserMapper;
import com.ssm.mapper.UserProfileMapper;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.provisioning.UserDetailsManager;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.util.*;

//这里必须加上@Service以供security.xml加载
@Service
public class MyUserDetailService implements UserDetailsManager,UserDetailsService{

	protected final Log logger = LogFactory.getLog(this.getClass());
	private  Map<String, MutableUserDetails> users = new HashMap<>();

	@Autowired
	private SysUserMapper sysUserMapper;

	@Autowired
	private SysRoleMapper  sysRoleMapper;

	/**
	 * 根据用户名获取-单张表-的权限密码等信息
	 * UserDetails只是一个接口，所以返回的对象只要继承了这个接口就可以，给返回去的对象可以进行check就行，所以此处返回的对象可以自定义，以便生成token需要使用的对象属性。
	 * @param username
	 * @return
	 * @throws org.springframework.security.core.userdetails.UsernameNotFoundException
	 */
	@Override
	public UserDetails loadUserByUsername(String username)throws UsernameNotFoundException {

		SysUser  user = null;
		try {
			user = sysUserMapper.selectUserByUserName(username);
		} catch (UsernameNotFoundException e) {
			logger.error("get user "+"'"+username+"'"+"info from database failed cause:"+ e.getMessage());
			throw new  UsernameNotFoundException("loadUser failed check the database connect");
		}
		if(user==null)
		{
			logger.error("get user "+"'"+username+"'"+"info from database failed cause user name not found");
			throw new  UsernameNotFoundException("UsernameNotFound");
		}
		boolean enables = true;
		boolean accountNonExpired = true;
		boolean credentialsNonExpired = true;
		boolean accountNonLocked = true;
		Collection<GrantedAuthority> grantedAuths = getAuthorities(user);
		logger.info("user "+"'"+username+"'"+" traversal role to collection success");
		JWTUserDetails jwtUserDetails = new JWTUserDetails(user.getUserId(),user.getUsername(),user.getPassword(),enables,accountNonExpired,credentialsNonExpired,accountNonLocked,grantedAuths);
		return  jwtUserDetails;
	}

	/**
	 * 根据用户ID遍历出该用户的所有角色信息放入collection
	 * @param user
	 * @return
	 */
	private Collection<GrantedAuthority> getAuthorities(SysUser  user) {
		Collection<GrantedAuthority> grantedAuthorities = new ArrayList<GrantedAuthority>();
		/*GrantedAuthority是赋予到主体的权限。？？？*/
		Set<SysRole> userRoles= sysRoleMapper.getUserRoleAllByUserId(user.getUserId());
		for (SysRole userRole : userRoles){
			SimpleGrantedAuthority grantedAuthority = new SimpleGrantedAuthority(userRole.getRoleName());
			grantedAuthorities.add(grantedAuthority);
		}
		return grantedAuthorities;
	}

	@Override
	public void createUser(UserDetails userDetails) {
		Assert.isTrue(!this.userExists(userDetails.getUsername()));
		this.users.put(userDetails.getUsername().toLowerCase(), new MutableUser(userDetails));
	}

	@Override
	public void updateUser(UserDetails userDetails) {
		Assert.isTrue(!this.userExists(userDetails.getUsername()));
		this.users.put(userDetails.getUsername().toLowerCase(), new MutableUser(userDetails));
	}

	@Override
	public void deleteUser(String s) {
		this.users.remove(s.toLowerCase());
	}

	@Override
	public void changePassword(String s, String s1) {

	}

	@Override
	public boolean userExists(String s) {
		return this.users.containsKey(s.toLowerCase());
	}

}
